Introduction and Overview

This is the R-notebook associated with the cardiovasc-eda script, the analysis provided is on a self-constructed dataset containing panel data on world countries cardiovascular disease deaths, obesity and BMI rates, and GDP by year. Data was sourced from ourworldindata.org. The contents of this notebook will only pertain toward data exploration and visualization. I recommend you view the script and notebook on modeling or the README to get a better understanding of the modeling techniques used in this project.

Loading in the Data

We begin with loading in the data which has already been pre-processed for modeling and data-visualization (see data-cleaning script. Additionally, we load in all of the modules used in this notebook.

library(ggplot2)
library(tidyr)
library(plm)
library(gridExtra)
library(grid)
library(plotly)
library(ggpubr)
library(GGally)
library(naniar)
#Load in the data
final_data <- read.csv("final_data.csv")

Missing Values and Summary Statistics

This was briefly covered in the data-cleaning script, but we need to check our variables for missing data. The package naniar provides some useful pre-built image visualizations of this one of which is applied below. We see that the only variable with missing data is Gdp_Per_Capita, with only roughly 7% of observations missing. This should not be an issue as most recommendations for dropping a variable in an analysis advise only dropping at cutoffs of either .5 or .9.

vis_miss(final_data[,2:7])

Next we’ll look at summary statistics to get an overall idea of the distributions of our variables.

summary(final_data)
            Entity          Year      cardiovasc_deaths    mean_bmi     percent_obesity    percent_severe_obesity
 Afghanistan   :  27   Min.   :1990   Min.   : 79.36    Min.   :19.13   Min.   :0.007468   Min.   :0.0004075     
 Albania       :  27   1st Qu.:1996   1st Qu.:220.98    1st Qu.:23.16   1st Qu.:0.062833   1st Qu.:0.0134741     
 Algeria       :  27   Median :2003   Median :290.99    Median :25.29   Median :0.148336   Median :0.0344925     
 American Samoa:  27   Mean   :2003   Mean   :318.34    Mean   :24.93   Mean   :0.150160   Mean   :0.0429116     
 Andorra       :  27   3rd Qu.:2010   3rd Qu.:393.37    3rd Qu.:26.40   3rd Qu.:0.208306   3rd Qu.:0.0578847     
 Angola        :  27   Max.   :2016   Max.   :795.76    Max.   :34.36   Max.   :0.620377   Max.   :0.3593956     
 (Other)       :4617                                                                                             
 GDP_Per_Capita    
 Min.   :   247.4  
 1st Qu.:  2843.6  
 Median :  8444.5  
 Mean   : 15137.7  
 3rd Qu.: 20910.5  
 Max.   :129349.9  
 NA's   :343       

Scatterplot Matrix

We have five continuous variables in our data set, cardiovasc_deaths, mean_bmi, percent_obesity, percent_severe_obesity, and GDP_Per_Capita. A good first step in data exploration is to create scatterplots for the continuous variables and our response variable (cardiovasc_deaths.) This allows us to visually inspect the relationship between our variables, whether that be linear, or a more complex relationship which cannot be captures in summary statistics like Pearson’s correlation coefficient. Additionally, as humans tend to be heavily visually oriented creatures it gives us a good idea of the strength of these relationships.

As our data is panel-data (includes bot a spatial and time aspect) this complicates our ability to produce a scatter matrix. For now, we will overcome this by averaging over all years for a given country and treating country mean over the time period as the experimental unit.

#Group the data over all years and find means
grouped_rates <- final_data %>%  
  group_by(Entity) %>% 
  summarise(cardio_death_rate = mean(cardiovasc_deaths), obesity_rate = mean(percent_obesity), sev_obesity_rate = mean(percent_severe_obesity), gdp_country =mean(GDP_Per_Capita), meanbmi = mean(mean_bmi))
#Scatterplot matrix
ggpairs(grouped_rates[,2:6])

The first column shows us the scatter plots for our response variable and most of them appear to be uncorrelated, and with no discernable relationship, almost all correlations sit somewhere around zero, with only per capita GDP having a relationship which is distinguishable. However, if we visually inspect the plot it becomes clear there really is no clear relationship between cardiovasvular deaths and GDP_Per_capita (one which could withstand a point being removed or added.) We do witness some correlations between our features which may lead to problems with multi-collinearity if we choose to use linear models later on. For now, though we will need to explore our data with more granularity in order to extract meaningful relationships.

Time Series Plots

We can begin by reintroducing the time-series aspect of our data. However, to produce meaningful visualizations we can only do so by sacrificing some of our country level data. We will do so by filtering by wealth, looking at only the top ten wealthiest countries and plotting their continuous values as a function of time.

sorted<- final_data %>%  
  arrange(desc(GDP_Per_Capita)) 
list <- unique(sorted$Entity) 
list[1:10]
rich_countries<-final_data %>% 
  filter(final_data$Entity %in% list[1:10]) 

#plots the data
plot1 <- ggplot( rich_countries, 
           aes( Year, cardiovasc_deaths, color = Entity)) + 
     geom_line(size=1) +
  labs(x= '', y ='Disease Deaths Per 100,000')

plot2 <-ggplot( rich_countries, 
          aes( Year, percent_obesity, color = Entity)) + 
      geom_line(size=1) +
  labs(x= '', y ='Obesity Rate')


plot3 <-ggplot( rich_countries, 
                aes( Year, GDP_Per_Capita, color = Entity)) + 
  geom_line(size=1) +
  labs(x= '', y ='Per Capita GDP')
figure<-ggarrange(plot1, plot2, plot3, nrow=3,common.legend = TRUE,legend="right")
figure<-annotate_figure(figure,
                top = text_grob("Time Series for 10 Wealthiest Countries", color = "black", face = 'bold',size = 20))
figure

What we see in the above graph is pretty clear evidence that our data is non-stationary with respect to time, as obesity increases over time and cardiovascular deaths decrease over time. This likely obfuscated any relationship in our original scatter matrix. That said, we are limited to data from only the top income countries. To get around this we create a function which groups the data into different bins depending on their per_capita_gdp. I then use this function to create a scatterplot graph segmented by three years 1995, 2005, 2015. This graph should give us a good idea of the way the relationship between obesity and cardiovascular deaths changes with respect to time and wealth.


#Scatterplot for years 1995,2005, 2015 
segment_wealth <- function(req_year, segment_by){
  
  data_req_year <- final_data %>% 
    filter( Year  == req_year )
  
  data_req_year <- data_req_year %>%  
    arrange(desc(GDP_Per_Capita))
  
  data_req_year<-data_req_year %>% 
   na.omit(GDP_Per_Capita)
  
  data_req_year$Group <- 1
  
  segment_length<- floor(length(data_req_year$GDP_Per_Capita) /segment_by)
  for( i in 1:segment_by){
    if(i == 1){
      data_req_year[i:(i*segment_length),8] <- i
    }
    if(i == segment_by){
      data_req_year[((i-1)*segment_length):length(data_req_year$GDP_Per_Capita),8] <- i 
      
    }
    else{
  data_req_year[((i-1)*segment_length):(i*segment_length),8] <- i
    }
  }
  return(data_req_year)
}
#Create data
data_1995<-segment_wealth(1995,3)
data_2005<-segment_wealth(2005,3)
data_2015<-segment_wealth(2015,3)

#Make an interactive version of the plot 
#Change group variable
scatter_data <- rbind(data_1995, data_2005, data_2015)
scatter_data$Group<-scatter_data$Group %>% 
  as.character()
scatter_data[scatter_data == "1"] <-"High Income"
scatter_data[scatter_data == "2"] <-"Middle Income"
scatter_data[scatter_data == "3"] <-"Low Income"

#Create the figure
fig<-ggplot(scatter_data, 
       aes(percent_obesity, cardiovasc_deaths, text = paste0("Country: ", Entity), color=Group))+
  geom_point(size=2)+
  facet_wrap(~Year, ncol = 3) +
  labs( x="Percent of Population Obese", y="Cardiovascular Disease Deaths", title ="Cardiovascular Disease vs. Obesity by Income Group")+
  theme(plot.title = element_text(hjust = .5,size = 20, face = "bold")) +
  scale_color_discrete(name = "")
ggplotly(fig, tooltip = "text") %>% 
  layout(showlegend = TRUE, legend=list(title=list(text='<b> Country Group </b>')), yaxis = list(fixedrange = TRUE,showgrid = F),
         xaxis = list(fixedrange = TRUE,showgrid = F, hovermode = "x")) %>% 
  config(displayModeBar = FALSE)

NA

Cross Sections by Time

The above figure is an interactive graph produced using plotly. The most interesting aspect for our analysis is the ability to isolate the relationship between obesity and cardiovascular disease at different income levels. We can do by selecting the group on the right-hand side. Now, we start to see relationships appear in the data, specifically in high income countries. Let’s take this a step further and look at the Pearson correlation between obesity and cardiovascular deaths as time changes. We do so by writing a function which returns a dataframe containing the correlations at each income level and the year. Then we construct a second time series plot to analyze the relationship over time.

#Graph a timeseries of the corelation between our response and explanatory variables
#Create the function
get_corelations <- function(){
  corelations <- data.frame()
  for(i in 1990:2016){
  yeardata <- segment_wealth(i, 3)
  yeardata <-yeardata %>% 
    group_by(factor(Group)) %>% 
    summarise(cor(GDP_Per_Capita, cardiovasc_deaths), cor(percent_obesity, cardiovasc_deaths), cor(percent_severe_obesity, cardiovasc_deaths), cor(mean_bmi, cardiovasc_deaths))
  yeardata[,6] <- i
  corelations <- rbind(corelations, yeardata)
  }
  names(corelations) <-c("Group","GDP_cor", "Obesity_cor", "sev_obesity_cor", "mean_bmi_cor", "Year")
  corelations$Group<-corelations$Group %>% 
    as.character()
  corelations[corelations == "1"] <-"High Income"
  corelations[corelations == "2"] <-"Middle Income"
  corelations[corelations == "3"] <-"Low Income"
  return(corelations)
}

finalcorelations <- get_corelations()

#Plot the Time series 
fig1<-ggplot(finalcorelations, aes(Year, Obesity_cor, color = Group))+
  labs( y="% Obese", x="Years")+
  geom_line(linetype= "twodash", size=2)

fig2<-ggplot(finalcorelations, aes(Year, sev_obesity_cor, color = Group))+
  labs( y="% Severely Obese", x="Years")+
  geom_line(linetype= "twodash", size=2)

fig3<-ggplot(finalcorelations, aes(Year, mean_bmi_cor, color = Group))+
  labs( y="Mean BMI ", x="Years")+
  geom_line(linetype= "twodash", size=2)

fig4<-ggplot(finalcorelations, aes(Year, GDP_cor, color = Group))+
  labs( y="GDP Per Capita", x="Years")+
  geom_line(linetype= "twodash", size=2)

#Arrange into grid
figure3<-ggarrange(fig1, fig2, fig3, fig4, nrow=4,common.legend = TRUE,legend="right")

#Add title
figure3 <-annotate_figure(figure3,
                top = text_grob("Time Series of Correlation between Cardiovascular Disease and Explanatory Variables", color = "black", size = 16))
figure3

Thea above lot shows that most of the relationships appear to be consistent over time, however most noticeably mean_bmi among high income groups does appear to be time variant. This is something which we will need to take account in our modeling. The next notebook in this repository will cover modeling.

LS0tDQp0aXRsZTogIkVEQSBGb3IgQ2FyZGlvdmFzY3VsYXIgRGlzZWFzZSBQcm9qZWN0Ig0Kb3V0cHV0OiBodG1sX25vdGVib29rDQotLS0NCg0KIyMgSW50cm9kdWN0aW9uIGFuZCBPdmVydmlldw0KVGhpcyBpcyB0aGUgUi1ub3RlYm9vayBhc3NvY2lhdGVkIHdpdGggdGhlIGNhcmRpb3Zhc2MtZWRhIHNjcmlwdCwgdGhlIGFuYWx5c2lzIHByb3ZpZGVkIGlzIG9uIGEgc2VsZi1jb25zdHJ1Y3RlZCBkYXRhc2V0IGNvbnRhaW5pbmcgcGFuZWwgZGF0YSBvbiB3b3JsZCBjb3VudHJpZXMgY2FyZGlvdmFzY3VsYXIgZGlzZWFzZSBkZWF0aHMsIG9iZXNpdHkgYW5kIEJNSSByYXRlcywgYW5kIEdEUCBieSB5ZWFyLiBEYXRhIHdhcyBzb3VyY2VkIGZyb20gb3Vyd29ybGRpbmRhdGEub3JnLiBUaGUgY29udGVudHMgb2YgdGhpcyBub3RlYm9vayB3aWxsIG9ubHkgcGVydGFpbiB0b3dhcmQgZGF0YSBleHBsb3JhdGlvbiBhbmQgdmlzdWFsaXphdGlvbi4gSSByZWNvbW1lbmQgeW91IHZpZXcgdGhlIHNjcmlwdCBhbmQgbm90ZWJvb2sgb24gbW9kZWxpbmcgb3IgdGhlIFJFQURNRSB0byBnZXQgYSBiZXR0ZXIgdW5kZXJzdGFuZGluZyBvZiB0aGUgbW9kZWxpbmcgdGVjaG5pcXVlcyB1c2VkIGluIHRoaXMgcHJvamVjdC4gDQoNCiMjIyBMb2FkaW5nIGluIHRoZSBEYXRhDQpXZSBiZWdpbiB3aXRoIGxvYWRpbmcgaW4gdGhlIGRhdGEgd2hpY2ggaGFzIGFscmVhZHkgYmVlbiBwcmUtcHJvY2Vzc2VkIGZvciBtb2RlbGluZyBhbmQgZGF0YS12aXN1YWxpemF0aW9uIChzZWUgZGF0YS1jbGVhbmluZyBzY3JpcHQuIEFkZGl0aW9uYWxseSwgd2UgbG9hZCBpbiBhbGwgb2YgdGhlIG1vZHVsZXMgdXNlZCBpbiB0aGlzIG5vdGVib29rLiANCmBgYHtyfQ0KbGlicmFyeShnZ3Bsb3QyKQ0KbGlicmFyeSh0aWR5cikNCmxpYnJhcnkocGxtKQ0KbGlicmFyeShncmlkRXh0cmEpDQpsaWJyYXJ5KGdyaWQpDQpsaWJyYXJ5KHBsb3RseSkNCmxpYnJhcnkoZ2dwdWJyKQ0KbGlicmFyeShHR2FsbHkpDQpsaWJyYXJ5KG5hbmlhcikNCiNMb2FkIGluIHRoZSBkYXRhDQpmaW5hbF9kYXRhIDwtIHJlYWQuY3N2KCJmaW5hbF9kYXRhLmNzdiIpDQpgYGANCiMjIyBNaXNzaW5nIFZhbHVlcyBhbmQgU3VtbWFyeSBTdGF0aXN0aWNzIA0KVGhpcyB3YXMgYnJpZWZseSBjb3ZlcmVkIGluIHRoZSBkYXRhLWNsZWFuaW5nIHNjcmlwdCwgYnV0IHdlIG5lZWQgdG8gY2hlY2sgb3VyIHZhcmlhYmxlcyBmb3IgbWlzc2luZyBkYXRhLiBUaGUgcGFja2FnZSBuYW5pYXIgcHJvdmlkZXMgc29tZSB1c2VmdWwgcHJlLWJ1aWx0IGltYWdlIHZpc3VhbGl6YXRpb25zIG9mIHRoaXMgb25lIG9mIHdoaWNoIGlzIGFwcGxpZWQgYmVsb3cuIFdlIHNlZSB0aGF0IHRoZSBvbmx5IHZhcmlhYmxlIHdpdGggbWlzc2luZyBkYXRhIGlzIEdkcF9QZXJfQ2FwaXRhLCB3aXRoIG9ubHkgcm91Z2hseSA3JSBvZiBvYnNlcnZhdGlvbnMgbWlzc2luZy4gVGhpcyBzaG91bGQgbm90IGJlIGFuIGlzc3VlIGFzIG1vc3QgcmVjb21tZW5kYXRpb25zIGZvciBkcm9wcGluZyBhIHZhcmlhYmxlIGluIGFuIGFuYWx5c2lzIGFkdmlzZSBvbmx5IGRyb3BwaW5nIGF0IGN1dG9mZnMgb2YgZWl0aGVyIC41IG9yIC45Lg0KYGBge3IsIGZpZy53aWR0aD0xMCwgZmlnLmhlaWdodD03fQ0KdmlzX21pc3MoZmluYWxfZGF0YVssMjo3XSkNCmBgYA0KTmV4dCB3ZSdsbCBsb29rIGF0IHN1bW1hcnkgc3RhdGlzdGljcyB0byBnZXQgYW4gb3ZlcmFsbCBpZGVhIG9mIHRoZSBkaXN0cmlidXRpb25zIG9mIG91ciB2YXJpYWJsZXMuIA0KYGBge3J9DQpzdW1tYXJ5KGZpbmFsX2RhdGEpDQoNCmBgYA0KDQojIyMgU2NhdHRlcnBsb3QgTWF0cml4DQpXZSBoYXZlIGZpdmUgY29udGludW91cyB2YXJpYWJsZXMgaW4gb3VyIGRhdGEgc2V0LCBjYXJkaW92YXNjX2RlYXRocywgbWVhbl9ibWksIHBlcmNlbnRfb2Jlc2l0eSwgcGVyY2VudF9zZXZlcmVfb2Jlc2l0eSwgYW5kIEdEUF9QZXJfQ2FwaXRhLiBBIGdvb2QgZmlyc3Qgc3RlcCBpbiBkYXRhIGV4cGxvcmF0aW9uIGlzIHRvIGNyZWF0ZSBzY2F0dGVycGxvdHMgZm9yIHRoZSBjb250aW51b3VzIHZhcmlhYmxlcyBhbmQgb3VyIHJlc3BvbnNlIHZhcmlhYmxlIChjYXJkaW92YXNjX2RlYXRocy4pIFRoaXMgYWxsb3dzIHVzIHRvIHZpc3VhbGx5IGluc3BlY3QgdGhlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIG91ciB2YXJpYWJsZXMsIHdoZXRoZXIgdGhhdCBiZSBsaW5lYXIsIG9yIGEgbW9yZSBjb21wbGV4IHJlbGF0aW9uc2hpcCB3aGljaCBjYW5ub3QgYmUgY2FwdHVyZXMgaW4gc3VtbWFyeSBzdGF0aXN0aWNzIGxpa2UgUGVhcnNvbuKAmXMgY29ycmVsYXRpb24gY29lZmZpY2llbnQuIEFkZGl0aW9uYWxseSwgYXMgaHVtYW5zIHRlbmQgdG8gYmUgaGVhdmlseSB2aXN1YWxseSBvcmllbnRlZCBjcmVhdHVyZXMgaXQgZ2l2ZXMgdXMgYSBnb29kIGlkZWEgb2YgdGhlIHN0cmVuZ3RoIG9mIHRoZXNlIHJlbGF0aW9uc2hpcHMuDQoNCkFzIG91ciBkYXRhIGlzIHBhbmVsLWRhdGEgKGluY2x1ZGVzIGJvdCBhIHNwYXRpYWwgYW5kIHRpbWUgYXNwZWN0KSB0aGlzIGNvbXBsaWNhdGVzIG91ciBhYmlsaXR5IHRvIHByb2R1Y2UgYSBzY2F0dGVyIG1hdHJpeC4gRm9yIG5vdywgd2Ugd2lsbCBvdmVyY29tZSB0aGlzIGJ5IGF2ZXJhZ2luZyBvdmVyIGFsbCB5ZWFycyBmb3IgYSBnaXZlbiBjb3VudHJ5IGFuZCB0cmVhdGluZyBjb3VudHJ5IG1lYW4gb3ZlciB0aGUgdGltZSBwZXJpb2QgYXMgdGhlIGV4cGVyaW1lbnRhbCB1bml0Lg0KDQpgYGB7ciwgcmVzdWx0cz0naGlkZScsIGZpZy53aWR0aD0xMCwgZmlnLmhlaWdodD03LCBmaWcuYWxpZ249Y2VudGVyfQ0KI0dyb3VwIHRoZSBkYXRhIG92ZXIgYWxsIHllYXJzIGFuZCBmaW5kIG1lYW5zDQpncm91cGVkX3JhdGVzIDwtIGZpbmFsX2RhdGEgJT4lICANCiAgZ3JvdXBfYnkoRW50aXR5KSAlPiUgDQogIHN1bW1hcmlzZShjYXJkaW9fZGVhdGhfcmF0ZSA9IG1lYW4oY2FyZGlvdmFzY19kZWF0aHMpLCBvYmVzaXR5X3JhdGUgPSBtZWFuKHBlcmNlbnRfb2Jlc2l0eSksIHNldl9vYmVzaXR5X3JhdGUgPSBtZWFuKHBlcmNlbnRfc2V2ZXJlX29iZXNpdHkpLCBnZHBfY291bnRyeSA9bWVhbihHRFBfUGVyX0NhcGl0YSksIG1lYW5ibWkgPSBtZWFuKG1lYW5fYm1pKSkNCiNTY2F0dGVycGxvdCBtYXRyaXgNCmdncGFpcnMoZ3JvdXBlZF9yYXRlc1ssMjo2XSkNCmBgYA0KVGhlIGZpcnN0IGNvbHVtbiBzaG93cyB1cyB0aGUgc2NhdHRlciBwbG90cyBmb3Igb3VyIHJlc3BvbnNlIHZhcmlhYmxlIGFuZCBtb3N0IG9mIHRoZW0gYXBwZWFyIHRvIGJlIHVuY29ycmVsYXRlZCwgYW5kIHdpdGggbm8gZGlzY2VybmFibGUgcmVsYXRpb25zaGlwLCBhbG1vc3QgYWxsIGNvcnJlbGF0aW9ucyBzaXQgc29tZXdoZXJlIGFyb3VuZCB6ZXJvLCB3aXRoIG9ubHkgcGVyIGNhcGl0YSBHRFAgaGF2aW5nIGEgcmVsYXRpb25zaGlwIHdoaWNoIGlzIGRpc3Rpbmd1aXNoYWJsZS4gSG93ZXZlciwgaWYgd2UgdmlzdWFsbHkgaW5zcGVjdCB0aGUgcGxvdCBpdCBiZWNvbWVzIGNsZWFyIHRoZXJlIHJlYWxseSBpcyBubyBjbGVhciByZWxhdGlvbnNoaXAgYmV0d2VlbiBjYXJkaW92YXN2dWxhciBkZWF0aHMgYW5kIEdEUF9QZXJfY2FwaXRhIChvbmUgd2hpY2ggY291bGQgd2l0aHN0YW5kIGEgcG9pbnQgYmVpbmcgcmVtb3ZlZCBvciBhZGRlZC4pIFdlIGRvIHdpdG5lc3Mgc29tZSBjb3JyZWxhdGlvbnMgYmV0d2VlbiBvdXIgZmVhdHVyZXMgd2hpY2ggbWF5IGxlYWQgdG8gcHJvYmxlbXMgd2l0aCBtdWx0aS1jb2xsaW5lYXJpdHkgaWYgd2UgY2hvb3NlIHRvIHVzZSBsaW5lYXIgbW9kZWxzIGxhdGVyIG9uLiBGb3Igbm93LCB0aG91Z2ggd2Ugd2lsbCBuZWVkIHRvIGV4cGxvcmUgb3VyIGRhdGEgd2l0aCBtb3JlIGdyYW51bGFyaXR5IGluIG9yZGVyIHRvIGV4dHJhY3QgbWVhbmluZ2Z1bCByZWxhdGlvbnNoaXBzLg0KDQoNCiMjIyBUaW1lIFNlcmllcyBQbG90cw0KV2UgY2FuIGJlZ2luIGJ5IHJlaW50cm9kdWNpbmcgdGhlIHRpbWUtc2VyaWVzIGFzcGVjdCBvZiBvdXIgZGF0YS4gSG93ZXZlciwgdG8gcHJvZHVjZSBtZWFuaW5nZnVsIHZpc3VhbGl6YXRpb25zIHdlIGNhbiBvbmx5IGRvIHNvIGJ5IHNhY3JpZmljaW5nIHNvbWUgb2Ygb3VyIGNvdW50cnkgbGV2ZWwgZGF0YS4gV2Ugd2lsbCBkbyBzbyBieSBmaWx0ZXJpbmcgYnkgd2VhbHRoLCBsb29raW5nIGF0IG9ubHkgdGhlIHRvcCB0ZW4gd2VhbHRoaWVzdCBjb3VudHJpZXMgYW5kIHBsb3R0aW5nIHRoZWlyIGNvbnRpbnVvdXMgdmFsdWVzIGFzIGEgZnVuY3Rpb24gb2YgdGltZS4gDQpgYGB7ciwgIHJlc3VsdHM9J2hpZGUnLCBtZXNzYWdlPUZBTFNFLCBmaWcuc2hvdz0naGlkZSd9DQpzb3J0ZWQ8LSBmaW5hbF9kYXRhICU+JSAgDQogIGFycmFuZ2UoZGVzYyhHRFBfUGVyX0NhcGl0YSkpIA0KbGlzdCA8LSB1bmlxdWUoc29ydGVkJEVudGl0eSkgDQpsaXN0WzE6MTBdDQoNCnJpY2hfY291bnRyaWVzPC1maW5hbF9kYXRhICU+JSANCiAgZmlsdGVyKGZpbmFsX2RhdGEkRW50aXR5ICVpbiUgbGlzdFsxOjEwXSkgDQoNCiNwbG90cyB0aGUgZGF0YQ0KcGxvdDEgPC0gZ2dwbG90KCByaWNoX2NvdW50cmllcywgDQogICAgICAgICAgIGFlcyggWWVhciwgY2FyZGlvdmFzY19kZWF0aHMsIGNvbG9yID0gRW50aXR5KSkgKyANCiAgICAgZ2VvbV9saW5lKHNpemU9MSkgKw0KICBsYWJzKHg9ICcnLCB5ID0nRGlzZWFzZSBEZWF0aHMgUGVyIDEwMCwwMDAnKQ0KDQpwbG90MiA8LWdncGxvdCggcmljaF9jb3VudHJpZXMsIA0KICAgICAgICAgIGFlcyggWWVhciwgcGVyY2VudF9vYmVzaXR5LCBjb2xvciA9IEVudGl0eSkpICsgDQogICAgICBnZW9tX2xpbmUoc2l6ZT0xKSArDQogIGxhYnMoeD0gJycsIHkgPSdPYmVzaXR5IFJhdGUnKQ0KDQoNCnBsb3QzIDwtZ2dwbG90KCByaWNoX2NvdW50cmllcywgDQogICAgICAgICAgICAgICAgYWVzKCBZZWFyLCBHRFBfUGVyX0NhcGl0YSwgY29sb3IgPSBFbnRpdHkpKSArIA0KICBnZW9tX2xpbmUoc2l6ZT0xKSArDQogIGxhYnMoeD0gJycsIHkgPSdQZXIgQ2FwaXRhIEdEUCcpDQpmaWd1cmU8LWdnYXJyYW5nZShwbG90MSwgcGxvdDIsIHBsb3QzLCBucm93PTMsY29tbW9uLmxlZ2VuZCA9IFRSVUUsbGVnZW5kPSJyaWdodCIpDQpmaWd1cmU8LWFubm90YXRlX2ZpZ3VyZShmaWd1cmUsDQogICAgICAgICAgICAgICAgdG9wID0gdGV4dF9ncm9iKCJUaW1lIFNlcmllcyBmb3IgMTAgV2VhbHRoaWVzdCBDb3VudHJpZXMiLCBjb2xvciA9ICJibGFjayIsIGZhY2UgPSAnYm9sZCcsc2l6ZSA9IDIwKSkNCg0KDQpgYGANCg0KYGBge3IsIGZpZy53aWR0aD0xMSwgZmlnLmhlaWdodD04LGZpZy5hbGlnbiA9ICdjZW50ZXInfQ0KZmlndXJlDQpgYGANCldoYXQgd2Ugc2VlIGluIHRoZSBhYm92ZSBncmFwaCBpcyBwcmV0dHkgY2xlYXIgZXZpZGVuY2UgdGhhdCBvdXIgZGF0YSBpcyBub24tc3RhdGlvbmFyeSB3aXRoIHJlc3BlY3QgdG8gdGltZSwgYXMgb2Jlc2l0eSBpbmNyZWFzZXMgb3ZlciB0aW1lIGFuZCBjYXJkaW92YXNjdWxhciBkZWF0aHMgZGVjcmVhc2Ugb3ZlciB0aW1lLiBUaGlzIGxpa2VseSBvYmZ1c2NhdGVkIGFueSByZWxhdGlvbnNoaXAgaW4gb3VyIG9yaWdpbmFsIHNjYXR0ZXIgbWF0cml4LiBUaGF0IHNhaWQsIHdlIGFyZSBsaW1pdGVkIHRvIGRhdGEgZnJvbSBvbmx5IHRoZSB0b3AgaW5jb21lIGNvdW50cmllcy4gVG8gZ2V0IGFyb3VuZCB0aGlzIHdlIGNyZWF0ZSBhIGZ1bmN0aW9uIHdoaWNoIGdyb3VwcyB0aGUgZGF0YSBpbnRvIGRpZmZlcmVudCBiaW5zIGRlcGVuZGluZyBvbiB0aGVpciBwZXJfY2FwaXRhX2dkcC4gSSB0aGVuIHVzZSB0aGlzIGZ1bmN0aW9uIHRvIGNyZWF0ZSBhIHNjYXR0ZXJwbG90IGdyYXBoIHNlZ21lbnRlZCBieSB0aHJlZSB5ZWFycyAxOTk1LCAyMDA1LCAyMDE1LiBUaGlzIGdyYXBoIHNob3VsZCBnaXZlIHVzIGEgZ29vZCBpZGVhIG9mIHRoZSB3YXkgdGhlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIG9iZXNpdHkgYW5kIGNhcmRpb3Zhc2N1bGFyIGRlYXRocyBjaGFuZ2VzIHdpdGggcmVzcGVjdCB0byB0aW1lIGFuZCB3ZWFsdGguIA0KYGBge3IsIHJlc3VsdHM9J2hpZGUnLCBtZXNzYWdlPUZBTFNFLH0NCg0KI1NjYXR0ZXJwbG90IGZvciB5ZWFycyAxOTk1LDIwMDUsIDIwMTUgDQpzZWdtZW50X3dlYWx0aCA8LSBmdW5jdGlvbihyZXFfeWVhciwgc2VnbWVudF9ieSl7DQogIA0KICBkYXRhX3JlcV95ZWFyIDwtIGZpbmFsX2RhdGEgJT4lIA0KICAgIGZpbHRlciggWWVhciAgPT0gcmVxX3llYXIgKQ0KICANCiAgZGF0YV9yZXFfeWVhciA8LSBkYXRhX3JlcV95ZWFyICU+JSAgDQogICAgYXJyYW5nZShkZXNjKEdEUF9QZXJfQ2FwaXRhKSkNCiAgDQogIGRhdGFfcmVxX3llYXI8LWRhdGFfcmVxX3llYXIgJT4lIA0KICAgbmEub21pdChHRFBfUGVyX0NhcGl0YSkNCiAgDQogIGRhdGFfcmVxX3llYXIkR3JvdXAgPC0gMQ0KICANCiAgc2VnbWVudF9sZW5ndGg8LSBmbG9vcihsZW5ndGgoZGF0YV9yZXFfeWVhciRHRFBfUGVyX0NhcGl0YSkgL3NlZ21lbnRfYnkpDQogIGZvciggaSBpbiAxOnNlZ21lbnRfYnkpew0KICAgIGlmKGkgPT0gMSl7DQogICAgICBkYXRhX3JlcV95ZWFyW2k6KGkqc2VnbWVudF9sZW5ndGgpLDhdIDwtIGkNCiAgICB9DQogICAgaWYoaSA9PSBzZWdtZW50X2J5KXsNCiAgICAgIGRhdGFfcmVxX3llYXJbKChpLTEpKnNlZ21lbnRfbGVuZ3RoKTpsZW5ndGgoZGF0YV9yZXFfeWVhciRHRFBfUGVyX0NhcGl0YSksOF0gPC0gaSANCiAgICAgIA0KICAgIH0NCiAgICBlbHNlew0KICBkYXRhX3JlcV95ZWFyWygoaS0xKSpzZWdtZW50X2xlbmd0aCk6KGkqc2VnbWVudF9sZW5ndGgpLDhdIDwtIGkNCiAgICB9DQogIH0NCiAgcmV0dXJuKGRhdGFfcmVxX3llYXIpDQp9DQpgYGANCg0KYGBge3IgZmlnLndpZHRoPTExLCBmaWcuaGVpZ2h0PTR9DQojQ3JlYXRlIGRhdGENCmRhdGFfMTk5NTwtc2VnbWVudF93ZWFsdGgoMTk5NSwzKQ0KZGF0YV8yMDA1PC1zZWdtZW50X3dlYWx0aCgyMDA1LDMpDQpkYXRhXzIwMTU8LXNlZ21lbnRfd2VhbHRoKDIwMTUsMykNCg0KI01ha2UgYW4gaW50ZXJhY3RpdmUgdmVyc2lvbiBvZiB0aGUgcGxvdCANCiNDaGFuZ2UgZ3JvdXAgdmFyaWFibGUNCnNjYXR0ZXJfZGF0YSA8LSByYmluZChkYXRhXzE5OTUsIGRhdGFfMjAwNSwgZGF0YV8yMDE1KQ0Kc2NhdHRlcl9kYXRhJEdyb3VwPC1zY2F0dGVyX2RhdGEkR3JvdXAgJT4lIA0KICBhcy5jaGFyYWN0ZXIoKQ0Kc2NhdHRlcl9kYXRhW3NjYXR0ZXJfZGF0YSA9PSAiMSJdIDwtIkhpZ2ggSW5jb21lIg0Kc2NhdHRlcl9kYXRhW3NjYXR0ZXJfZGF0YSA9PSAiMiJdIDwtIk1pZGRsZSBJbmNvbWUiDQpzY2F0dGVyX2RhdGFbc2NhdHRlcl9kYXRhID09ICIzIl0gPC0iTG93IEluY29tZSINCg0KI0NyZWF0ZSB0aGUgZmlndXJlDQpmaWc8LWdncGxvdChzY2F0dGVyX2RhdGEsIA0KICAgICAgIGFlcyhwZXJjZW50X29iZXNpdHksIGNhcmRpb3Zhc2NfZGVhdGhzLCB0ZXh0ID0gcGFzdGUwKCJDb3VudHJ5OiAiLCBFbnRpdHkpLCBjb2xvcj1Hcm91cCkpKw0KICBnZW9tX3BvaW50KHNpemU9MikrDQogIGZhY2V0X3dyYXAoflllYXIsIG5jb2wgPSAzKSArDQogIGxhYnMoIHg9IlBlcmNlbnQgb2YgUG9wdWxhdGlvbiBPYmVzZSIsIHk9IkNhcmRpb3Zhc2N1bGFyIERpc2Vhc2UgRGVhdGhzIiwgdGl0bGUgPSJDYXJkaW92YXNjdWxhciBEaXNlYXNlIHZzLiBPYmVzaXR5IGJ5IEluY29tZSBHcm91cCIpKw0KICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gLjUsc2l6ZSA9IDIwLCBmYWNlID0gImJvbGQiKSkgKw0KICBzY2FsZV9jb2xvcl9kaXNjcmV0ZShuYW1lID0gIiIpDQpnZ3Bsb3RseShmaWcsIHRvb2x0aXAgPSAidGV4dCIpICU+JSANCiAgbGF5b3V0KHNob3dsZWdlbmQgPSBUUlVFLCBsZWdlbmQ9bGlzdCh0aXRsZT1saXN0KHRleHQ9JzxiPiBDb3VudHJ5IEdyb3VwIDwvYj4nKSksIHlheGlzID0gbGlzdChmaXhlZHJhbmdlID0gVFJVRSxzaG93Z3JpZCA9IEYpLA0KICAgICAgICAgeGF4aXMgPSBsaXN0KGZpeGVkcmFuZ2UgPSBUUlVFLHNob3dncmlkID0gRiwgaG92ZXJtb2RlID0gIngiKSkgJT4lIA0KICBjb25maWcoZGlzcGxheU1vZGVCYXIgPSBGQUxTRSkNCg0KYGBgDQojIyMgQ3Jvc3MgU2VjdGlvbnMgYnkgVGltZQ0KVGhlIGFib3ZlIGZpZ3VyZSBpcyBhbiBpbnRlcmFjdGl2ZSBncmFwaCBwcm9kdWNlZCB1c2luZyBwbG90bHkuIFRoZSBtb3N0IGludGVyZXN0aW5nIGFzcGVjdCBmb3Igb3VyIGFuYWx5c2lzIGlzIHRoZSBhYmlsaXR5IHRvIGlzb2xhdGUgdGhlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIG9iZXNpdHkgYW5kIGNhcmRpb3Zhc2N1bGFyIGRpc2Vhc2UgYXQgZGlmZmVyZW50IGluY29tZSBsZXZlbHMuIFdlIGNhbiBkbyBieSBzZWxlY3RpbmcgdGhlIGdyb3VwIG9uIHRoZSByaWdodC1oYW5kIHNpZGUuIE5vdywgd2Ugc3RhcnQgdG8gc2VlIHJlbGF0aW9uc2hpcHMgYXBwZWFyIGluIHRoZSBkYXRhLCBzcGVjaWZpY2FsbHkgaW4gaGlnaCBpbmNvbWUgY291bnRyaWVzLiBMZXQncyB0YWtlIHRoaXMgYSBzdGVwIGZ1cnRoZXIgYW5kIGxvb2sgYXQgdGhlIFBlYXJzb24gY29ycmVsYXRpb24gYmV0d2VlbiBvYmVzaXR5IGFuZCBjYXJkaW92YXNjdWxhciBkZWF0aHMgYXMgdGltZSBjaGFuZ2VzLiBXZSBkbyBzbyBieSB3cml0aW5nIGEgZnVuY3Rpb24gd2hpY2ggcmV0dXJucyBhIGRhdGFmcmFtZSBjb250YWluaW5nIHRoZSBjb3JyZWxhdGlvbnMgYXQgZWFjaCBpbmNvbWUgbGV2ZWwgYW5kIHRoZSB5ZWFyLiBUaGVuIHdlIGNvbnN0cnVjdCBhIHNlY29uZCB0aW1lIHNlcmllcyBwbG90IHRvIGFuYWx5emUgdGhlIHJlbGF0aW9uc2hpcCBvdmVyIHRpbWUuIA0KDQpgYGB7ciwgcmVzdWx0cz0naGlkZScsIG1lc3NhZ2U9RkFMU0UsIGZpZy5zaG93PSdoaWRlJ30NCiNHcmFwaCBhIHRpbWVzZXJpZXMgb2YgdGhlIGNvcmVsYXRpb24gYmV0d2VlbiBvdXIgcmVzcG9uc2UgYW5kIGV4cGxhbmF0b3J5IHZhcmlhYmxlcw0KI0NyZWF0ZSB0aGUgZnVuY3Rpb24NCmdldF9jb3JlbGF0aW9ucyA8LSBmdW5jdGlvbigpew0KICBjb3JlbGF0aW9ucyA8LSBkYXRhLmZyYW1lKCkNCiAgZm9yKGkgaW4gMTk5MDoyMDE2KXsNCiAgeWVhcmRhdGEgPC0gc2VnbWVudF93ZWFsdGgoaSwgMykNCiAgeWVhcmRhdGEgPC15ZWFyZGF0YSAlPiUgDQogICAgZ3JvdXBfYnkoZmFjdG9yKEdyb3VwKSkgJT4lIA0KICAgIHN1bW1hcmlzZShjb3IoR0RQX1Blcl9DYXBpdGEsIGNhcmRpb3Zhc2NfZGVhdGhzKSwgY29yKHBlcmNlbnRfb2Jlc2l0eSwgY2FyZGlvdmFzY19kZWF0aHMpLCBjb3IocGVyY2VudF9zZXZlcmVfb2Jlc2l0eSwgY2FyZGlvdmFzY19kZWF0aHMpLCBjb3IobWVhbl9ibWksIGNhcmRpb3Zhc2NfZGVhdGhzKSkNCiAgeWVhcmRhdGFbLDZdIDwtIGkNCiAgY29yZWxhdGlvbnMgPC0gcmJpbmQoY29yZWxhdGlvbnMsIHllYXJkYXRhKQ0KICB9DQogIG5hbWVzKGNvcmVsYXRpb25zKSA8LWMoIkdyb3VwIiwiR0RQX2NvciIsICJPYmVzaXR5X2NvciIsICJzZXZfb2Jlc2l0eV9jb3IiLCAibWVhbl9ibWlfY29yIiwgIlllYXIiKQ0KICBjb3JlbGF0aW9ucyRHcm91cDwtY29yZWxhdGlvbnMkR3JvdXAgJT4lIA0KICAgIGFzLmNoYXJhY3RlcigpDQogIGNvcmVsYXRpb25zW2NvcmVsYXRpb25zID09ICIxIl0gPC0iSGlnaCBJbmNvbWUiDQogIGNvcmVsYXRpb25zW2NvcmVsYXRpb25zID09ICIyIl0gPC0iTWlkZGxlIEluY29tZSINCiAgY29yZWxhdGlvbnNbY29yZWxhdGlvbnMgPT0gIjMiXSA8LSJMb3cgSW5jb21lIg0KICByZXR1cm4oY29yZWxhdGlvbnMpDQp9DQoNCmZpbmFsY29yZWxhdGlvbnMgPC0gZ2V0X2NvcmVsYXRpb25zKCkNCg0KI1Bsb3QgdGhlIFRpbWUgc2VyaWVzIA0KZmlnMTwtZ2dwbG90KGZpbmFsY29yZWxhdGlvbnMsIGFlcyhZZWFyLCBPYmVzaXR5X2NvciwgY29sb3IgPSBHcm91cCkpKw0KICBsYWJzKCB5PSIlIE9iZXNlIiwgeD0iWWVhcnMiKSsNCiAgZ2VvbV9saW5lKGxpbmV0eXBlPSAidHdvZGFzaCIsIHNpemU9MikNCg0KZmlnMjwtZ2dwbG90KGZpbmFsY29yZWxhdGlvbnMsIGFlcyhZZWFyLCBzZXZfb2Jlc2l0eV9jb3IsIGNvbG9yID0gR3JvdXApKSsNCiAgbGFicyggeT0iJSBTZXZlcmVseSBPYmVzZSIsIHg9IlllYXJzIikrDQogIGdlb21fbGluZShsaW5ldHlwZT0gInR3b2Rhc2giLCBzaXplPTIpDQoNCmZpZzM8LWdncGxvdChmaW5hbGNvcmVsYXRpb25zLCBhZXMoWWVhciwgbWVhbl9ibWlfY29yLCBjb2xvciA9IEdyb3VwKSkrDQogIGxhYnMoIHk9Ik1lYW4gQk1JICIsIHg9IlllYXJzIikrDQogIGdlb21fbGluZShsaW5ldHlwZT0gInR3b2Rhc2giLCBzaXplPTIpDQoNCmZpZzQ8LWdncGxvdChmaW5hbGNvcmVsYXRpb25zLCBhZXMoWWVhciwgR0RQX2NvciwgY29sb3IgPSBHcm91cCkpKw0KICBsYWJzKCB5PSJHRFAgUGVyIENhcGl0YSIsIHg9IlllYXJzIikrDQogIGdlb21fbGluZShsaW5ldHlwZT0gInR3b2Rhc2giLCBzaXplPTIpDQoNCiNBcnJhbmdlIGludG8gZ3JpZA0KZmlndXJlMzwtZ2dhcnJhbmdlKGZpZzEsIGZpZzIsIGZpZzMsIGZpZzQsIG5yb3c9NCxjb21tb24ubGVnZW5kID0gVFJVRSxsZWdlbmQ9InJpZ2h0IikNCg0KI0FkZCB0aXRsZQ0KZmlndXJlMyA8LWFubm90YXRlX2ZpZ3VyZShmaWd1cmUzLA0KICAgICAgICAgICAgICAgIHRvcCA9IHRleHRfZ3JvYigiVGltZSBTZXJpZXMgb2YgQ29ycmVsYXRpb24gYmV0d2VlbiBDYXJkaW92YXNjdWxhciBEaXNlYXNlIGFuZCBFeHBsYW5hdG9yeSBWYXJpYWJsZXMiLCBjb2xvciA9ICJibGFjayIsIHNpemUgPSAxNikpDQpgYGANCg0KYGBge3IsIGZpZy53aWR0aD0xMSwgZmlnLmhlaWdodD04LGZpZy5hbGlnbiA9ICdjZW50ZXInfQ0KZmlndXJlMw0KYGBgDQpUaGVhIGFib3ZlIGxvdCBzaG93cyB0aGF0IG1vc3Qgb2YgdGhlIHJlbGF0aW9uc2hpcHMgYXBwZWFyIHRvIGJlIGNvbnNpc3RlbnQgb3ZlciB0aW1lLCBob3dldmVyIG1vc3Qgbm90aWNlYWJseSBtZWFuX2JtaSBhbW9uZyBoaWdoIGluY29tZSBncm91cHMgZG9lcyBhcHBlYXIgdG8gYmUgdGltZSB2YXJpYW50LiBUaGlzIGlzIHNvbWV0aGluZyB3aGljaCB3ZSB3aWxsIG5lZWQgdG8gdGFrZSBhY2NvdW50IGluIG91ciBtb2RlbGluZy4gVGhlIG5leHQgbm90ZWJvb2sgaW4gdGhpcyByZXBvc2l0b3J5IHdpbGwgY292ZXIgbW9kZWxpbmcuIA0K